package geektime.concurrent.part2.race;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 多线程选手操作的类
 */
public class MultiThreadPlayer {
    private static final int GEN_RANDOM_NUMBERS_THREAD_QUANTITY = 1;
    private static final int SORT_COMPUTE_THREAD_QUANTITY = Runtime.getRuntime().availableProcessors() + 2;

    private MultiThreadShareData shareData;

    public long genRandomNumbersAndCompute() throws InterruptedException {
        shareData = new MultiThreadShareData(GEN_RANDOM_NUMBERS_THREAD_QUANTITY, SORT_COMPUTE_THREAD_QUANTITY);
        ExecutorService genRandomNumbersThreadPool = Executors.newFixedThreadPool(GEN_RANDOM_NUMBERS_THREAD_QUANTITY);
        ExecutorService sortComputeThreadPool = Executors.newFixedThreadPool(SORT_COMPUTE_THREAD_QUANTITY);
        System.out.println("------多线程选手开始工作了------");
        long t0 = System.currentTimeMillis();
        for (int i = 0; i < GEN_RANDOM_NUMBERS_THREAD_QUANTITY; i++) {
            Thread genRandomNumberThread =
                new Thread(new MultiThreadGenWorker(i, shareData.COUNT / GEN_RANDOM_NUMBERS_THREAD_QUANTITY, shareData));
            genRandomNumbersThreadPool.execute(genRandomNumberThread);
        }
        // 这里使用await()方法来阻塞当前线程的操作，确保生成随机数的操作结束后才进行后续动作
        shareData.getGenRandomLatch().await();
        System.out.println("多线程选手生成随机数的数量=" + shareData.getScoreList().size());
        long t1 = System.currentTimeMillis();

        for (int i = 0; i < SORT_COMPUTE_THREAD_QUANTITY; i++) {
            Thread sortComputeThread =
                new Thread(new MultiThreadComputeWorker(i, shareData.COUNT / SORT_COMPUTE_THREAD_QUANTITY, shareData));
            sortComputeThreadPool.execute(sortComputeThread);
        }
        // 这里使用await()方法来阻塞当前线程的操作，确保排序计算的操作结束后才进行后续动作
        shareData.getSortComputeLatch().await();
        // main线程打印结果
        printTop10();
        long t2 = System.currentTimeMillis();
        System.out.printf("多线程选手生成随机数耗时=%s，排序计算耗时=%s，总耗时=%s\n", (t1 - t0), (t2 - t1), (t2 - t0));
        // 所有任务都执行完毕后关闭线程池
        genRandomNumbersThreadPool.shutdown();
        sortComputeThreadPool.shutdown();
        return (t2 - t0);
    }

    private void printTop10() {
        Integer[] topArray = shareData.getExchange().toArray(new Integer[shareData.getExchange().size()]);
        Integer[] top10Array = MultiThreadComputeWorker.findTop10BySort(topArray);
        System.out.println("多线程选手生成的最大的数据TOP10：" + Arrays.toString(top10Array));
    }
}
